#ifndef __define_h__
#define __define_h__

#include "system.h"
#include "types.h"

/*
 * @brief: disable copy and assign constructor.
 */
#define DISABLE_COPY_AND_ASSIGN( theClass )\
    theClass( const theClass & );\
    void operator=( const theClass & );

namespace core
{



#define makedword(a, b)      ((dword)(((word)(((dword)(a)) & 0xffff)) | ((dword)((word)(((dword)(b)) & 0xffff))) << 16))
#define loword(l)            ((word)(((dword)(l)) & 0xffff))
#define hiword(l)            ((word)((((dword)(l)) >> 16) & 0xffff))





/*
 * @brief: define the face object trait
 */
enum FaceObjectTrait
{
    FACE_OBJECT_TRAIT_CONTROL,
    FACE_OBJECT_TRAIT_STYLE
};





/*
 * @brief: base class
 */
class FaceObject
{
public:
    FaceObject(){}
    virtual ~FaceObject(){}

    virtual bool SetAttribute( const char *lpszName, const char *lpszValue, uint &lResult ) = 0;
    virtual FaceObjectTrait Trait() = 0;
};





/*
 * @brief: attribute map
 */
enum
{
    ATTRIBUTE_TRAIT_NULL        = 0x00000000,
    ATTRIBUTE_TRAIT_LAYOUT      = 0x00000001,
    ATTRIBUTE_TRAIT_PAINT       = 0x00000002
};
#define DECLARE_ATTRIBUTE_MAP()\
    virtual bool SetAttribute( const char *lpszName, const char *lpszValue, uint &lResult );

#define BEGIN_ATTRIBUTE_MAP(obj)\
    bool obj::SetAttribute(\
        const char *lpszName,\
        const char *lpszValue,\
        uint &lResult )\
    {\
        lResult = 0;\
        if( !lpszName || !lpszValue )\
        {\
            return false;\
        }\
        bool bRet;

#define END_ATTRIBUTE_MAP()\
            bRet = false;\
        \
        return bRet;\
    }

#define CHAIN_ATTRIBUTE_MAP(theclass)\
        if( theclass::SetAttribute( lpszName, lpszValue, lResult ) )\
        {\
            bRet = true;\
        }\
        else

#define CHAIN_MEMBER_ATTRIBUTE_MAP(themember)\
        if( themember.SetAttribute( lpszName, lpszValue, lResult ) )\
        {\
            bRet = true;\
        }\
        else
 
#define ATTRIBUTE_INT(attribname, varname, state)\
        if( strcmp( lpszName, attribname ) == 0 )\
        {\
            varname = string2int(lpszValue);\
            bRet = true;\
            lResult = state;\
        }\
        else

#define ATTRIBUTE_LONG(attribname, varname, state)\
        if( strcmp( lpszName, attribname ) == 0 )\
        {\
            varname = string2long(lpszValue);\
            bRet = true;\
            lResult = state;\
        }\
        else

#define ATTRIBUTE_DWORD(attribname, varname, state)\
        if( strcmp( lpszName, attribname ) == 0 )\
        {\
            varname = (dword)string2dword(lpszValue, 0, 10);\
            bRet = true;\
            lResult = state;\
        }\
        else

#define ATTRIBUTE_STRING(attribname, varname, state)\
        if( strcmp( lpszName, attribname ) == 0 )\
        {\
            varname = lpszValue;\
            bRet = true;\
            lResult = state;\
        }\
        else

#define ATTRIBUTE_WSTRING(attribname, varname, state)\
        if( strcmp( lpszName, attribname ) == 0 )\
        {\
            varname = base::utf8tounicode(lpszValue);\
            bRet = true;\
            lResult = state;\
        }\
        else

#define ATTRIBUTE_COLOR(attribname, varname, state)\
        if( strcmp( lpszName, attribname ) == 0 )\
        {\
            color_functor fn;\
            varname = fn(lpszValue);\
            bRet = true;\
            lResult = state;\
        }\
        else

#define ATTRIBUTE_UNIT(attribname, varname, state)\
        if( strcmp( lpszName, attribname ) == 0 )\
        {\
            unit_functor fn;\
            varname = fn(lpszValue);\
            bRet = true;\
            lResult = state;\
        }\
        else

#define ATTRIBUTE_PIXEL(attribname, varname, state)\
        if( strcmp( lpszName, attribname ) == 0 )\
        {\
            pixel_functor fn;\
            varname = fn(lpszValue);\
            bRet = true;\
            lResult = state;\
        }\
        else

#define ATTRIBUTE_FILE(attribname, varname, state)\
        if( strcmp( lpszName, attribname ) == 0 )\
        {\
            file_functor fn;\
            varname = fn(lpszValue);\
            bRet = true;\
            lResult = state;\
        }\
        else

#define ATTRIBUTE_PARSER(attribname, parser, state)\
        if( strcmp( lpszName, attribname ) == 0 )\
        {\
            parser(lpszValue);\
            bRet = true;\
            lResult = state;\
        }\
        else

#define ATTRIBUTE_ENUM_BEGIN(attribname, vartype)\
        if( strcmp( lpszName, attribname ) == 0 )\
        {\
            vartype varTemp;

#define ATTRIBUTE_ENUM_VALUE(enumstring, enumvalue)\
            if( strcmp( lpszValue, enumstring ) == 0 )\
            {\
                varTemp = enumvalue;\
                bRet = true;\
            }\
            else

#define ATTRIBUTE_ENUM_END(varname, state)\
                bRet = false;\
            if( bRet )\
            {\
                varname = varTemp;\
                lResult = state;\
            }\
        }\
        else




/*
 * @brief: background repeat
 */
enum
{
    BACKGROUND_REPEAT_NULL    = 0x00000000,
    BACKGROUND_REPEAT_X       = 0x00000001,
    BACKGROUND_REPEAT_Y       = 0x00000002
};





/*
 * @brief: position type
 */
enum
{
    POSITION_ABSOLUTE        = 0x00000001,
    POSITION_RELATIVE        = 0x00000002
};





/*
 * @brief: fit content type
 */
enum
{
    FIT_TYPE_NULL          = 0x00000000,
    FIT_TYPE_WIDTH         = 0x00000001,
    FIT_TYPE_HEIGHT        = 0x00000002,
    FIT_TYPE_BOTH          = 0x00000003
};





/*
 * @brief: alignment
 */
enum
{
    ALIGNMENT_UNDEFINE            = 0x00000000,

    HORIZONTAL_ALIGNMENT_LEFT     = 0x00000001,
    HORIZONTAL_ALIGNMENT_CENTER   = 0x00000002,
    HORIZONTAL_ALIGNMENT_RIGHT    = 0x00000004,

    VERTICAL_ALIGNMENT_TOP        = 0x00000010,
    VERTICAL_ALIGNMENT_MIDDLE     = 0x00000020,
    VERTICAL_ALIGNMENT_BOTTOM     = 0x00000040
};





/*
 * @brief: font style
 */
enum
{
    FONT_STYLE_NORMAL         = 0x00000000,
    FONT_STYLE_BOLD           = 0x00000001,
    FONT_STYLE_ITALIC         = 0x00000002,
    FONT_STYLE_BOLD_ITALIC    = 0x00000003,
    FONT_STYLE_UNDERLINE      = 0x00000004
};





/*
 * @brief: border style
 */
enum
{
    BORDER_STYLE_SOLID        = 0x00000001,
    BORDER_STYLE_DASHED       = 0x00000002,
    BORDER_STYLE_DOTTED       = 0x00000004
};





/*
 * @brief: position type
 */
enum
{
    POSITION_TYPE_LEFT_TOP         = 0x00000001,
    POSITION_TYPE_LEFT_BOTTOM      = 0x00000002,
    POSITION_TYPE_RIGHT_TOP        = 0x00000004,
    POSITION_TYPE_RIGHT_BOTTOM     = 0x00000008
};





/*
 * @brief: cursor
 */
enum
{
    CURSOR_TYPE_ARROW     = 0x00000001,
    CURSOR_TYPE_HAND      = 0x00000002
};





/*
 * @brief: state
 */
enum FaceState
{
    FACE_STATE_NORMAL     = 0x00000001,
    FACE_STATE_HOVER      = 0x00000002,
    FACE_STATE_DOWN       = 0x00000004,
    FACE_STATE_FOCUS      = 0x00000008
};





/*
 * @brief: control state
 */
enum WindowState
{
    WINDOW_STATE_CONSTRUCTED,
    WINDOW_STATE_LOADED,
    WINDOW_STATE_LAYOUTED,
    WINDOW_STATE_READY
};





/*
 * @brief: message map
 */
enum
{
    FM_LOAD,
    FM_LAYOUT,
    FM_ADJUST,
    FM_PAINT,
    FM_MOUSEHOVER,
    FM_MOUSELEAVE,
    FM_LBUTTONDOWN,
    FM_LBUTTONUP,
    FM_MOUSEWHEEL,
    FM_RBUTTONDOWN,
    FM_RBUTTONUP,
    FM_KEYDOWN,
    FM_KEYUP,
    FM_CHAR
};

#define BEGIN_MESSAGE_MAP()\
    virtual bool ProcessMessage( uint uMsg, uint wParam, uint lParam, uint &lResult )\
    {\
        bool bHandle = false;

#define END_MESSAGE_MAP()\
            bHandle = false;\
        return bHandle;\
    }

#define MESSAGE_HANDLE( msg, func )\
    if( msg == uMsg )\
    {\
        lResult = func( wParam, lParam );\
        bHandle = true;\
    }\
    else

#define CHAIN_MESSAGE_MAP(theclass)\
    if( theclass::ProcessMessage( uMsg, wParam, lParam, lResult ) )\
    {\
        bHandle = true;\
    }\
    else





/*
 * @brief: observer map
 */
class FaceWindow;
class IMessageObserver
{
public:
    virtual bool OnMessageObserver( FaceWindow * control, uint uMsg, uint wParam, uint lParam, bool bBefore ) = 0;
};
class IMessageFilter
{
public:
    virtual bool OnMessageFilter( FaceWindow * control, uint uMsg, uint wParam, uint lParam, uint &lResult ) = 0;
};

#define BEGIN_CONTROL_MESSAGE_MAP()\
    virtual bool OnMessageObserver( core::FaceWindow * control, core::uint uMsg, core::uint wParam, core::uint lParam, bool bBefore )\
    {\
        bool bHandle = false;

#define END_CONTROL_MESSAGE_MAP()\
            bHandle = false;\
        return bHandle;\
    }

#define CONTROL_MESSAGE_HANDLE( msg, id, before, func )\
        if( bBefore == before &&\
            (uMsg == msg) &&\
            (strcmp( ((std::string)(*control)).c_str(), id ) == 0) )\
        {\
            func( id, wParam, lParam );\
            bHandle = true;\
        }\
        else

#define CHAIN_CONTROL_MESSAGE_MAP(theClass)\
        if( theClass::OnMessageObserver( control, uMsg, wParam, lParam, bBefore ) )\
        {\
            bHandle = true;\
        }\
        else

#define CONTROL_LBUTTONUP( id, func ) CONTROL_MESSAGE_HANDLE( core::FM_LBUTTONUP, id, false, func )
#define CONTROL_MOUSEOVER( id, func ) CONTROL_MESSAGE_HANDLE( core::FM_MOUSEHOVER, id, false, func )





/*
 * @brief: handle delegate
 */
class HandleDelegate
{
public:
    virtual bool Drag() = 0;
    virtual bool Update( const core::rect& rect ) = 0;
};





};


/*
 * @brief: dynamic create
 */
typedef core::FaceObject* (API *DYNAMIC_CREATE_FN )( const char * );
struct RuntimeClass
{
    static RuntimeClass *m_pFirstClass;
    static core::FaceObject * CreateObject( const char * );

    DYNAMIC_CREATE_FN m_pfnCreateObject;
    RuntimeClass * m_pNextClass;
};

struct class_init
{
    class_init( RuntimeClass *pNewClass )
    {
        pNewClass->m_pNextClass = RuntimeClass::m_pFirstClass;
        RuntimeClass::m_pFirstClass = pNewClass;
    }
};

#define DECLARE_DYNAMIC_CREATE(class_name)\
public:\
    static RuntimeClass class##class_name;\
    static core::FaceObject *API CreateObject( const char * );

#define IMPLY_DYNAMIC_CREATE(class_name, tag_name)\
    RuntimeClass class_name::class##class_name =\
    {\
        class_name::CreateObject,\
        0\
    };\
    static class_init _init_##class_name( &class_name::class##class_name );\
    core::FaceObject * class_name::CreateObject( const char * value )\
    {\
        if( strcmp( value,tag_name ) == 0 )\
            return new class_name;\
        \
        return 0;\
    }



#endif